/*
 * @Version: V1.0
 * @Project: MGS组件 All rights Reserved, Designed By www.supermap.com
 * @Title:
 * @Package: mgs-webui-basic
 * @Description:
 * @Author: 李卫欣
 * @Date: 2021-06-20 23:00:11
 * @Copyright: 2021 www.supermap.com Inc. All rights reserved.
 * @注意: 本内容仅限于北京超图信息技术有限公司内部传阅，禁止外泄以及用于其他的商业目的
 */
import type { BindMap } from 'types'
import * as Cesium from 'Cesium'
import {
    getCGCS2000Prj,
    getWGS84_CGCS2000,
    getCGCS2000FDXFromLng,
} from '@/utils/projection'

export default class KilometerGridPlugin {
    static extends = [
        'openKilometerGrid', //打开公里网
        'closeKilometerGrid', //关闭公里网
        'openKGLabel', //打开公里网注记(没有公里网时，会开启公里网)
        'closeKGLabel', //关闭公里网注记
    ]

    //注记显示开关
    private showKGLable__!: Boolean

    //地图对象Cesium.viewer
    private map: any

    //内存绘制层
    private kilometerGridGroup__ = new Cesium.CustomDataSource()

    //内存绘注记制层
    private kGLabelGroup__ = new Cesium.CustomDataSource()

    //公里网显示开关
    private isOpen__ = false

    //当前视口范围
    private currentBounds__!: number[]

    //当前视口比例
    private currentZoomLvl__ = 1

    //插件归属的vue对象
    private vmParent: any

    //公里网 样式
    private kilometerGridStyle__: any

    constructor(vm: BindMap) {
        this.vmParent = vm
        this.map = vm.map
        this.map.dataSources.add(this.kilometerGridGroup__)
        this.map.dataSources.add(this.kGLabelGroup__)
        this.showKGLable__ = false
    }

    /**
     * 打开公里网
     */
    openKilometerGrid(isLabel: boolean = false, style: any) {
        this.isOpen__ = true
        this.showKGLable__ = isLabel
        this.kilometerGridStyle__ = style
        this.vmParent.$on('onZoomEnd', this._onMapZoomEnd.bind(this))
        this.drawKilometerGrid(
            this.vmParent.getZoom(),
            this.vmParent.getBounds()
        )
    }

    /**
     * 关闭公里网
     */
    closeKilometerGrid() {
        this.isOpen__ = false
        this.showKGLable__ = false
        this.kilometerGridStyle__ = {}
        this.vmParent.$off('onZoomEnd', this._onMapZoomEnd)
        this.kilometerGridGroup__.entities.removeAll()
        this.kGLabelGroup__.entities.removeAll()
    }

    /**
     * 打开公里网注记
     */
    openKGLabel() {
        this.showKGLable__ = true
        this.closeKilometerGrid()
        this.openKilometerGrid(true, this.kilometerGridStyle__)
    }

    /**
     * 关闭公里网注记
     */
    closeKGLabel() {
        this.showKGLable__ = false
        // this.closeKilometerGrid()
        // this.openKilometerGrid()
        this.kGLabelGroup__.entities.removeAll()
    }

    /**
     * 地图比例尺改变事件
     * @param e
     * @returns
     */
    _onMapZoomEnd(e: any) {
        this.currentBounds__ = this.vmParent.getBounds()
        this.currentZoomLvl__ = this.vmParent.getZoom()
        if (!this.isOpen__) {
            return
        }
        this.drawKilometerGrid(
            this.vmParent.getZoom(),
            this.vmParent.getBounds()
        )
    }

    /**
     * 绘制经纬网
     * @param zoomLvl 当前级别
     * @param bounds 当前范围
     */
    drawKilometerGrid(zoomLvl: number, bounds: number[]) {
        //清除原网格
        this.kilometerGridGroup__.entities.removeAll()
        this.kGLabelGroup__.entities.removeAll()
        //设置风格样式
        const selfStyle = Object.assign(
            {
                fontColor: this.kilometerGridStyle__.color || '#666',
                fill: this.kilometerGridStyle__.fill || true,
            },
            this.kilometerGridStyle__
        )
        this.kilometerGridStyle__ = selfStyle
        //计算跨度
        let step: number = 1000
        if (this.currentZoomLvl__ < 5) {
            step = 500000
        } else if (this.currentZoomLvl__ < 7) {
            step = 200000
        } else if (this.currentZoomLvl__ < 9) {
            step = 100000
        } else if (this.currentZoomLvl__ < 12) {
            step = 10000
        }
        //按CGCS高斯投影6度带绘制
        let w: number = bounds[0]
        let s: number = bounds[1]
        let e: number = bounds[2]
        let n: number = bounds[3]
        //保留刻度点坐标
        let lbW = w
        if (lbW < 72) {
            lbW = 72
        }
        let lbN = n
        if (lbN > 56) {
            lbN = 56
        }
        //w 72 s 138
        if (w < 72) {
            w = 72
        }
        if (s < 10) {
            s = 4
        }
        if (e > 138) {
            e = 138
        }
        if (n > 56) {
            n = 56
        }
        //坐标转换
        const posStart = getCGCS2000Prj([w, s])
        const posEnd = getCGCS2000Prj([e, n])
        let r = 0,
            c = 0
        let oldline: number[][] = []
        const dh_arr: number[] = []
        const self = this
        //组织方里网
        for (
            let x: number = Math.floor(posStart[0] / step) * step;
            x < posEnd[0] + step;
            x += step
        ) {
            let latlngTmp: any
            try {
                latlngTmp = getWGS84_CGCS2000([x, posStart[1]])
            } catch {
                continue
            }
            if (latlngTmp[0] < w) continue
            if (latlngTmp[0] > e) continue
            const newLine: number[][] = []
            for (
                let y: number = Math.floor(posStart[1] / step) * step;
                y < posEnd[1] + step;
                y += step
            ) {
                const latlng = getWGS84_CGCS2000([x, y])
                newLine.push(latlng)
                if (r > 0 && c > 0) {
                    this.kilometerGridGroup__.entities.add(
                        new Cesium.Entity({
                            polyline: new Cesium.PolylineGraphics({
                                positions: Cesium.Cartesian3.fromDegreesArray([
                                    oldline[c - 1][0],
                                    oldline[c - 1][1],
                                    newLine[c - 1][0],
                                    newLine[c - 1][1],
                                    latlng[0],
                                    latlng[1],
                                    oldline[c][0],
                                    oldline[c][1],
                                ]),
                                clampToGround: new Cesium.ConstantProperty(
                                    true
                                ),
                                width: new Cesium.ConstantProperty(2),
                                material: new Cesium.ColorMaterialProperty(
                                    Cesium.Color.fromCssColorString(
                                        selfStyle.fontColor
                                    )
                                ),
                            }),
                            polygon: new Cesium.PolygonGraphics({
                                hierarchy: new Cesium.PolygonHierarchy(
                                    Cesium.Cartesian3.fromDegreesArray([
                                        oldline[c - 1][0],
                                        oldline[c - 1][1],
                                        newLine[c - 1][0],
                                        newLine[c - 1][1],
                                        latlng[0],
                                        latlng[1],
                                        oldline[c][0],
                                        oldline[c][1],
                                    ])
                                ),
                                heightReference: new Cesium.ConstantProperty(
                                    Cesium.HeightReference.CLAMP_TO_GROUND
                                ),
                                material: new Cesium.ColorMaterialProperty(
                                    Cesium.Color.TRANSPARENT
                                ),
                            }),
                        })
                    )
                    //添加刻度
                    if (r === 1 && this.showKGLable__) {
                        //纬度
                        const strY: string = y + ''
                        this.vmParent.drawGraphic(
                            'Label',
                            [lbW, latlng[1]],
                            {
                                text: `${strY.substring(0, 2)}(${strY.substring(
                                    2,
                                    5
                                )})`,
                                disableDepthTestDistance:
                                    Number.POSITIVE_INFINITY,
                                offset: [-45, 0],
                                ...selfStyle,
                            },
                            null,
                            this.kilometerGridGroup__
                        )
                    }
                    if (c === 1 && this.showKGLable__) {
                        //经度
                        const strX: string = x + ''
                        const dh: number = getCGCS2000FDXFromLng(latlng[0])
                        if (dh !== 0) {
                            if (!dh_arr.includes(dh)) {
                                dh_arr.push(dh)
                                this.vmParent.drawGraphic(
                                    'Label',
                                    [latlng[0], lbN],
                                    {
                                        text: `${dh}d(${latlng[0]}°)`,
                                        disableDepthTestDistance:
                                            Number.POSITIVE_INFINITY,
                                        offset: [0, -25],
                                        ...selfStyle,
                                    },
                                    null,
                                    this.kilometerGridGroup__
                                )
                            }
                        } else {
                            this.vmParent.drawGraphic(
                                'Label',
                                [latlng[0], lbN],
                                {
                                    text: `${strX.substring(
                                        0,
                                        2
                                    )}(${strX.substring(2, 5)})`,
                                    disableDepthTestDistance:
                                        Number.POSITIVE_INFINITY,
                                    offset: [0, -25],
                                    ...selfStyle,
                                },
                                null,
                                this.kilometerGridGroup__
                            )
                        }
                    }
                }
                c++
            }
            oldline = newLine
            r++
            c = 0
        }
    }
}
